package lee.study.fanshe;


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectClassDemo {

    public static void reflectNewInstance() {//1、通过反射拿到一个类的实例
        try {
            Class<?> classStudent = Class.forName("lee.study.fanshe.Student");
            Object objectStudent = classStudent.newInstance();
            Student student = (Student) objectStudent;
            System.out.println("获得学生对象:" + student);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void reflectPrivateConstructor() {//2、通过反射拿到私有的构造方法取修改定义的对象
        try {
            Class<?> classStudent = Class.forName("lee.study.fanshe.Student");//拿到反射对象
            //注意传入对应的参数，此处应为String和int
            Constructor<?> declaredConstructorStudent = classStudent.getDeclaredConstructor(String.class, int.class);//通过反射的对象来调用他的私有构造方法

            //Constructor<?> declaredConstructorStudent=classStudent.getConStructor();拿到不带参数的构造方法，↑的拿到的是带参的

            declaredConstructorStudent.setAccessible(true);//设置为true之后可修改访问权限

            Object objectStudent = declaredConstructorStudent.newInstance("lee", 21);
            Student student = (Student) objectStudent;
            System.out.println("获得私有构造函数且修改姓名和年龄为:" + student);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void reflectPrivateField() {//3、通过反射拿到私有的属性并修改
        try {
            Class<?> classStudent = Class.forName("lee.study.fanshe.Student");
            Field field = classStudent.getDeclaredField("name");
            field.setAccessible(true);
            //可以修改属性的值
            Object objectStudent = classStudent.newInstance();
            Student student = (Student) objectStudent;
            //field.set的两个参数--->>1、要修改的对象  2、修改的值
            field.set(student, "lee");
            //用get方法拿到修改后的student的属性，强转为String型输出(不强转默认为Object型)
            String name = (String) field.get(student);
            System.out.println("反射私有属性修改了name:" + name);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void reflectPrivateMethod() {
        try {
            Class<?> classStudent = Class.forName("lee.study.fanshe.Student");

            //第一个参数为反射的函数名称  第二个参数为反射方法的形参
            Method methodStudent = classStudent.getDeclaredMethod("function", String.class);

            System.out.println("私有的方法名为:" + methodStudent.getName());
            methodStudent.setAccessible(true); //私有的一般都要加这句，才可以修改

            Object objectStudent = classStudent.newInstance();
            Student student = (Student) objectStudent;
            methodStudent.invoke(student, "我是给私有function函数传递的参数");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //reflectNewInstance();
        //reflectPrivateConstructor();
        //reflectPrivateField();
        reflectPrivateMethod();
    }
}
